package com.ruoyi.system.basicInformation.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.utils.BaiduToWgs84;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.JsonUtil;
import com.ruoyi.system.basicInformation.domain.Annotations;
import com.ruoyi.system.basicInformation.domain.TTerminalGpsData;
import com.ruoyi.system.basicInformation.service.ITTerminalService;
import com.ruoyi.system.basicInformation.vo.TTerminalVo;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.ruoyi.system.basicInformation.bo.TTerminalTrajectoryAddBo;
import com.ruoyi.system.basicInformation.bo.TTerminalTrajectoryQueryBo;
import com.ruoyi.system.basicInformation.bo.TTerminalTrajectoryEditBo;
import com.ruoyi.system.basicInformation.domain.TTerminalTrajectory;
import com.ruoyi.system.basicInformation.mapper.TTerminalTrajectoryMapper;
import com.ruoyi.system.basicInformation.vo.TTerminalTrajectoryVo;
import com.ruoyi.system.basicInformation.service.ITTerminalTrajectoryService;

import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 终端轨迹Service业务层处理
 *
 * @author ruoyi
 * @date 2021-05-20
 */
@Service
public class TTerminalTrajectoryServiceImpl extends ServiceImpl<TTerminalTrajectoryMapper, TTerminalTrajectory> implements ITTerminalTrajectoryService {
    @Autowired
    private ITTerminalService iTTerminalService;

    @Override
    public TTerminalTrajectoryVo queryById(Long id) {
        TTerminalTrajectory db = this.baseMapper.selectById(id);
        return BeanUtil.toBean(db, TTerminalTrajectoryVo.class);
    }

    @Override
    public List<HashMap> getListByDate(TTerminalTrajectoryQueryBo bo) {
        if ((bo.getTerminalType().equals("1") || bo.getTerminalType().equals("2") || bo.getTerminalType().equals("4")) && StrUtil.isNotBlank(bo.getTerminalType()))
            return this.baseMapper.getListByDate(bo);
        else
            return null;
    }

    @Override
    public List<TTerminalTrajectoryVo> queryList(TTerminalTrajectoryQueryBo bo) {
        List<TTerminalTrajectoryVo> tTerminalTrajectoryVoList = new ArrayList<>();
        if (bo.getTerminalType().equals("1") || bo.getTerminalType().equals("2") || bo.getTerminalType().equals("4")) {
            LambdaQueryWrapper<TTerminalTrajectory> lqw = Wrappers.lambdaQuery();
            lqw.eq(StrUtil.isNotBlank(bo.getTerminalType()), TTerminalTrajectory::getTerminalType, bo.getTerminalType());
            lqw.eq(TTerminalTrajectory::getTerminalId, bo.getTerminalId());
            // lqw.eq(bo.getProduceTime() != null, TTerminalTrajectory::getProduceTime, bo.getProduceTime());
            lqw.between(TTerminalTrajectory::getCreateTime, bo.getBeginDate(), bo.getOverDate());
            tTerminalTrajectoryVoList = entity2Vo(this.list(lqw.orderByAsc(TTerminalTrajectory::getCreateTime)));
//            double[] wgs84=new double[2];
//            BaiduToWgs84 bd=new BaiduToWgs84();
//            for (TTerminalTrajectoryVo in:tTerminalTrajectoryVoList) {
//                wgs84 = bd.FromXY(in.getX().doubleValue(),in.getY().doubleValue());
//                in.setX(new BigDecimal(wgs84[0]));
//                in.setY(new BigDecimal(wgs84[1]));
//            }
        } else {
            try {

                long beginTime = bo.getBeginDate().getTime();
                long endTime = bo.getOverDate().getTime();
                TTerminalVo tTerminalVo = iTTerminalService.queryById(bo.getTerminalId());
                //从第三方接口，根据终端ID，终端类型，时间范围获取轨迹数据
                String resultGps = httpRequestHttpClient("http://10.10.45.15:44081/api/query", "POST", "{\"start\":\"" + beginTime + "\",\"end\":\"" + endTime + "\",\"showTSUIDs\":\"true\",\"noAnnotations\":false,\"queries\":[{\"aggregator\":\"none\",\"metric\":\"bdgfnew\",\"tags\":{\"terminalId\":\"" + tTerminalVo.getEquipmentNumber() + "\"}}]}", true);
                if (StringUtils.isNotEmpty(resultGps)) {

                    Console.log("终端ID===" + bo.getTerminalId() + "==轨迹数据===" + resultGps);

                    resultGps = resultGps.substring(1, resultGps.length() - 1);

                    TTerminalGpsData tTerminalGpsData = JsonUtil.parseJsonToBean(resultGps, TTerminalGpsData.class);

                    if (tTerminalGpsData != null) {
                        for (TTerminalGpsData.AnnotationsBean in : tTerminalGpsData.getAnnotations()) {

                            TTerminalTrajectoryVo tTerminalTrajectoryVo = new TTerminalTrajectoryVo();
                            tTerminalTrajectoryVo.setX(new BigDecimal(in.getCustom().getVLon()));
                            tTerminalTrajectoryVo.setY(new BigDecimal(in.getCustom().getVLat()));
                            tTerminalTrajectoryVo.setProduceTime(DateUtils.parseDate(in.getCustom().getVTime()));

                            tTerminalTrajectoryVoList.add(tTerminalTrajectoryVo);
                        }
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return tTerminalTrajectoryVoList;
    }

    /*
     * urlStr-请求地址
     * requestMethod-请求方式
     * requestParams-json参数字符串
     * isSecretCode-是否使用此参数
     * */
    private String httpRequest(String urlStr, String requestMethod, String requestParams, Boolean isSecretCode) {
        OutputStreamWriter out = null;
        BufferedReader br = null;
        String result = "";
        try {
            URL url = new URL(urlStr);
            //打开和url之间的连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //请求方式
            conn.setRequestMethod(requestMethod);

            //设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            if (isSecretCode) {
                conn.setRequestProperty("secretCode", "8deabf5c4b4f44c3a6c79c4a5e260d63-0");
            }


            //DoOutput设置是否向httpUrlConnection输出，DoInput设置是否从httpUrlConnection读入，此外发送post请求必须设置这两个
            conn.setDoOutput(true);
            conn.setDoInput(true);
            if (conn.getResponseCode() == 400) {
                Console.log("根据终端ID取轨迹数据接口报错" + "=====" + requestParams);
                return "";
            }
            /**
             * 下面的三句代码，就是调用第三方http接口
             */
            //获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
            //发送请求参数即数据
            out.write(requestParams);
            //flush输出流的缓冲
            out.flush();
            /**
             * 下面的代码相当于，获取调用第三方http接口后返回的结果
             */
            //获取URLConnection对象对应的输入流
            InputStream is = conn.getInputStream();
            //构造一个字符流缓存
            br = new BufferedReader(new InputStreamReader(is));
            String str = "";
            while ((str = br.readLine()) != null) {
                result += str;
            }

            //关闭流
            is.close();
            //断开连接，disconnect是在底层tcp socket链接空闲时才切断，如果正在被其他线程使用就不切断。
            conn.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    private String httpRequestHttpClient(String urlStr, String requestMethod, String requestParams, Boolean isSecretCode) {
        HttpClient client = new DefaultHttpClient();
        HttpPost request = new HttpPost(urlStr);
        String result = "";
        try {
            StringEntity postingString = new StringEntity(requestParams,
                    "utf-8");
            if (isSecretCode) {
                request.setHeader("secretCode", "8deabf5c4b4f44c3a6c79c4a5e260d63-0");
                request.setHeader("accept", "*/*");
                request.setHeader("connection", "Keep-Alive");
                request.setHeader("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
                request.setHeader("Content-Type", "application/json;charset=utf-8");
            }
            request.setEntity(postingString);
            HttpResponse resp = client.execute(request);
            //获取Http状态码
            int responseStatusCode = resp.getStatusLine().getStatusCode();
            if (responseStatusCode == 400) {
                Console.log("根据终端ID取轨迹数据接口报错" + "=====" + requestParams);
                return "";
            }
            HttpEntity entity = resp.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity, "UTF-8");//解析返回数据

                System.out.println(result);

            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public List<TTerminalTrajectoryVo> queryAlarmList() {
        return this.baseMapper.queryAlarmList();
    }

    /**
     * 实体类转化成视图对象
     *
     * @param collection 实体类集合
     * @return
     */
    private List<TTerminalTrajectoryVo> entity2Vo(Collection<TTerminalTrajectory> collection) {
        List<TTerminalTrajectoryVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, TTerminalTrajectoryVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<TTerminalTrajectory> page = (Page<TTerminalTrajectory>) collection;
            Page<TTerminalTrajectoryVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page, pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Override
    public Boolean insertByAddBo(TTerminalTrajectoryAddBo bo) {
        TTerminalTrajectory add = BeanUtil.toBean(bo, TTerminalTrajectory.class);
        validEntityBeforeSave(add);
        return this.save(add);
    }

    @Override
    public Boolean updateByEditBo(TTerminalTrajectoryEditBo bo) {
        TTerminalTrajectory update = BeanUtil.toBean(bo, TTerminalTrajectory.class);
        validEntityBeforeSave(update);
        return this.updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(TTerminalTrajectory entity) {

        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return this.removeByIds(ids);
    }
}
